package com.hundsun.cprs.yyt.service.quota.service.impl;

import com.hundsun.cprs.yyt.common.base.BaseService;
import com.hundsun.cprs.yyt.common.enums.EnumBusinessCode;
import com.hundsun.cprs.yyt.common.exception.ServiceCodeException;
import com.hundsun.cprs.yyt.service.account.enums.EnumQuotaTransType;
import com.hundsun.cprs.yyt.service.quota.dao.QuotaExchangeRecordDao;
import com.hundsun.cprs.yyt.service.quota.domain.Quota;
import com.hundsun.cprs.yyt.service.quota.domain.QuotaExchangeRecord;
import com.hundsun.cprs.yyt.service.quota.domain.QuotaHold;
import com.hundsun.cprs.yyt.service.quota.domain.query.QuotaExchangeRecordQuery;
import com.hundsun.cprs.yyt.service.quota.dto.QuotaExchangeRecordInfo;
import com.hundsun.cprs.yyt.service.quota.enums.EnumQuotaExchangeStatus;
import com.hundsun.cprs.yyt.service.quota.enums.EnumQuotaFreezeStatus;
import com.hundsun.cprs.yyt.service.quota.service.QuotaExchangeRecordService;
import com.hundsun.cprs.yyt.service.quota.service.QuotaHoldService;
import com.hundsun.cprs.yyt.service.quota.service.QuotaService;
import com.hundsun.cprs.yyt.util.DateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.Date;
import java.util.List;

/**
 * 配额兑换记录相关接口
 * @author herong22384
 * @date 2019/8/6 14:32
 */
@Service
public class QuotaExchangeRecordServiceImpl extends BaseService implements QuotaExchangeRecordService {

    @Autowired
    private QuotaExchangeRecordDao quotaExchangeRecordDao;
    @Autowired
    private QuotaHoldService quotaHoldService;
    @Autowired
    private QuotaService quotaService;

    @Override
    public void queryByPage(QuotaExchangeRecordQuery query) {
        List<QuotaExchangeRecordInfo> infos = quotaExchangeRecordDao.queryByPage(query);
        query.compatible(infos);
    }

    @Override
    public QuotaExchangeRecordInfo selectByRecordId(Long recordId) {
        return quotaExchangeRecordDao.selectByPrimaryKey(recordId);
    }

    @Override
    @Transactional
    public void exchange(Long userId, Long sourceQuotaId, Long aimQuotaId, Long amount) {
        //1.校验源配额是否充足
        QuotaHold quotaHold = quotaHoldService.getQuoteHoldByUserAndQuoteId(userId,sourceQuotaId);
        if (quotaHold == null){
            throw new ServiceCodeException(EnumBusinessCode.BUSINESS_3231.getErrorNo(),EnumBusinessCode.BUSINESS_3231.getErrorInfo());
        }
        if (quotaHold.getCanUseAmount() < amount){
            throw new ServiceCodeException(EnumBusinessCode.BUSINESS_3232.getErrorNo(),EnumBusinessCode.BUSINESS_3232.getErrorInfo());
        }
        Quota quota = quotaService.selectQuoteById(aimQuotaId);
        if (quota == null){
            throw new ServiceCodeException(EnumBusinessCode.BUSINESS_3233.getErrorNo(),EnumBusinessCode.BUSINESS_3233.getErrorInfo());
        }
        //2.扣减源配额
        quotaHoldService.deductQuota(userId,sourceQuotaId,amount,EnumQuotaTransType.TRANS_0101.getCode(),"通用配额转专用配额支出");
        //3.增加目标配额
        quotaHoldService.addQuota(userId,aimQuotaId,amount,EnumQuotaTransType.TRANS_0201.getCode(),"通用配额转专用配额收入");
        //判断该配额类型在兑换时是否需要冻结
        if (quota.getIsNeedFreeze().equals(EnumQuotaFreezeStatus.NEED_FREEZE.getCode())){
            //4.冻结目标配额
            quotaHoldService.freezeQuote(userId,aimQuotaId,amount,EnumQuotaTransType.TRANS_0301.getCode(),"通用配额转专用配额冻结");
            //5.生成需要解冻的配额兑换记录
            createUnfreezeExchangerecord(quotaHold,aimQuotaId,amount);
        }else {
            //6.生成不需要解冻的配额兑换记录
            createNofreezeExchangerecord(quotaHold,aimQuotaId,amount);
        }
    }

    @Override
    @Transactional
    public void unfreezeByHand(Long recordId, Long amount) {
        //1.校验配额兑换记录中的剩余数量是否充足
        QuotaExchangeRecord record = quotaExchangeRecordDao.selectByPrimaryKey(recordId);
        if (record == null){
            throw new ServiceCodeException(EnumBusinessCode.BUSINESS_3235.getErrorNo(),EnumBusinessCode.BUSINESS_3235.getErrorInfo());
        }
        if (record.getRemainingAmount() < amount){
            throw new ServiceCodeException(EnumBusinessCode.BUSINESS_3236.getErrorNo(),EnumBusinessCode.BUSINESS_3236.getErrorInfo());
        }
        if (record.getRemainingAmount() > amount){
            record.setStatus(EnumQuotaExchangeStatus.HANDLING.getCode());
        }else {
            record.setStatus(EnumQuotaExchangeStatus.COMPLETED.getCode());
            record.setNextFireTime(-1L);
        }
        //2.校验配额账户的冻结数量是否充足
        QuotaHold quotaHold = quotaHoldService.getQuoteHoldByUserAndQuoteId(record.getUserId(),record.getQuotaId());
        if (quotaHold == null){
            throw new ServiceCodeException(EnumBusinessCode.BUSINESS_3231.getErrorNo(),EnumBusinessCode.BUSINESS_3231.getErrorInfo());
        }
        if (quotaHold.getFreezeQuota() < amount){
            throw new ServiceCodeException(EnumBusinessCode.BUSINESS_3234.getErrorNo(),EnumBusinessCode.BUSINESS_3234.getErrorInfo());
        }

        //3.手工解冻
        quotaHoldService.unfreezeQuote(record.getUserId(),record.getQuotaId(),amount,EnumQuotaTransType.TRANS_0402.getCode(),"手工解冻");

        //4.更新配额兑换记录中的剩余量
        record.setRemainingAmount(amount);
        quotaExchangeRecordDao.updateByPrimaryKeySelective(record);
    }

    @Override
    public void unfreezeByQuartz() {
        //1.获取到所有待处理的兑换记录
        QuotaExchangeRecordQuery query = new QuotaExchangeRecordQuery();
        Integer[] statusArray = {EnumQuotaExchangeStatus.WAIT_HANDLE.getCode(),EnumQuotaExchangeStatus.HANDLING.getCode()};
        query.setStatusArray(statusArray);
        query.onlyReturnList();
        this.queryByPage(query);
        //2.遍历处理
        if (!CollectionUtils.isEmpty(query.getData())){
            for (QuotaExchangeRecord record : query.getData()){
                Long nowTime = new Date().getTime();
                if (record.getNextFireTime() <= nowTime){
                    //3.释放配额
                    releaseQuota(record);
                }
            }
        }
    }

    protected void createUnfreezeExchangerecord(QuotaHold quotaHold, Long quoteId, Long amount){
        //获取转换的配额类型元数据（相关释放规则）
        Quota quota = quotaService.selectQuoteById(quoteId);
        if (quota == null){
            throw new ServiceCodeException(EnumBusinessCode.BUSINESS_3233.getErrorNo(),EnumBusinessCode.BUSINESS_3233.getErrorInfo());
        }
        QuotaExchangeRecord quotaExchangeRecord = new QuotaExchangeRecord();
        quotaExchangeRecord.setExchangeTime(new Date());
        quotaExchangeRecord.setExchangeAmount(amount);
        quotaExchangeRecord.setFreezeAmount(amount);
        quotaExchangeRecord.setFundAccount(quotaHold.getFundAccount());
        //计算下一次释放时间
        Long nextFireTime = DateUtil.getNextDay(new Date(), quota.getUnfreezeCycle().intValue()).getTime();
        quotaExchangeRecord.setNextFireTime(nextFireTime);
        quotaExchangeRecord.setPrevFireTime(-1L);
        quotaExchangeRecord.setQuotaId(quoteId);
        quotaExchangeRecord.setRemainingAmount(amount);
        quotaExchangeRecord.setStatus(EnumQuotaExchangeStatus.WAIT_HANDLE.getCode());
        quotaExchangeRecord.setUnfreezeCycleInDays(quota.getUnfreezeCycle());
        quotaExchangeRecord.setUnfreezeNumInTimes(quota.getUnfreezeNumInTimes());
        quotaExchangeRecord.setUserId(quotaHold.getUserId());
        quotaExchangeRecordDao.insert(quotaExchangeRecord);
    }

    protected void createNofreezeExchangerecord(QuotaHold quotaHold, Long quoteId,Long amount){
        //获取转换的配额类型元数据（相关释放规则）
        Quota quota = quotaService.selectQuoteById(quoteId);
        if (quota == null){
            throw new ServiceCodeException(EnumBusinessCode.BUSINESS_3233.getErrorNo(),EnumBusinessCode.BUSINESS_3233.getErrorInfo());
        }
        QuotaExchangeRecord quotaExchangeRecord = new QuotaExchangeRecord();
        quotaExchangeRecord.setExchangeTime(new Date());
        quotaExchangeRecord.setExchangeAmount(amount);
        quotaExchangeRecord.setFreezeAmount(0L);
        quotaExchangeRecord.setFundAccount(quotaHold.getFundAccount());
        quotaExchangeRecord.setNextFireTime(-1L);
        quotaExchangeRecord.setPrevFireTime(-1L);
        quotaExchangeRecord.setQuotaId(quoteId);
        quotaExchangeRecord.setRemainingAmount(0L);
        quotaExchangeRecord.setStatus(EnumQuotaExchangeStatus.COMPLETED.getCode());
        quotaExchangeRecord.setUnfreezeCycleInDays(0L);
        quotaExchangeRecord.setUnfreezeNumInTimes(0L);
        quotaExchangeRecord.setUserId(quotaHold.getUserId());
        quotaExchangeRecordDao.insert(quotaExchangeRecord);
    }

    protected void releaseQuota(QuotaExchangeRecord record){
        try{
            record.setPrevFireTime(record.getNextFireTime());
            if (record.getRemainingAmount() <= record.getUnfreezeNumInTimes()){
                //如果当前剩余数量小于每次释放数量，则本次释放剩余数量
                quotaHoldService.unfreezeQuote(record.getUserId(),record.getQuotaId(),record.getRemainingAmount(),EnumQuotaTransType.TRANS_0401.getCode(),"定时解冻配额");
                record.setRemainingAmount(record.getRemainingAmount());
                record.setStatus(EnumQuotaExchangeStatus.COMPLETED.getCode());
                record.setNextFireTime(-1L);
            }else{
                //如果当前剩余数量大于等于每次释放数量，则本次释放每次释放数量
                quotaHoldService.unfreezeQuote(record.getUserId(),record.getQuotaId(),record.getUnfreezeNumInTimes(),EnumQuotaTransType.TRANS_0401.getCode(),"定时解冻配额");
                record.setRemainingAmount(record.getUnfreezeNumInTimes());
                record.setStatus(EnumQuotaExchangeStatus.HANDLING.getCode());
                Long nextFireTime = DateUtil.getNextDay(new Date(),record.getUnfreezeCycleInDays().intValue()).getTime();
                record.setNextFireTime(nextFireTime);
            }
            //更新配额兑换记录
            quotaExchangeRecordDao.updateByPrimaryKeySelective(record);
        }catch (Exception e){
            logger.error("配额兑换定时释放失败，recordId：" + record.getId()+",原因：" + e.getMessage());
        }
    }
}
